<template>
  <div class="course-3d">
    <!-- 3D渲染容器 -->
    <div ref="container3d" class="three-container"></div>
    
    <!-- UI控制层 -->
    <div class="ui-overlay">
      <!-- 顶部控制栏 -->
      <div class="top-controls">
        <div class="semester-selector">
          <button 
            v-for="(semester, index) in semesters" 
            :key="index"
            :class="['semester-btn', { active: currentSemester === index }]"
            @click="switchSemester(index)"
          >
            {{ semester.name }}
          </button>
        </div>
        
        <div class="search-controls">
          <div class="voice-search" @click="startVoiceSearch">
            <span class="voice-icon">🎤</span>
            <span>语音搜索</span>
          </div>
          <input 
            type="text" 
            v-model="searchQuery" 
            placeholder="搜索课程..."
            @input="filterCourses"
            class="search-input"
          >
        </div>
      </div>
      
      <!-- 课程信息悬浮卡片 -->
      <div 
        v-if="hoveredCourse" 
        class="course-info-card"
        :style="{ left: cardPosition.x + 'px', top: cardPosition.y + 'px' }"
      >
        <h3>{{ hoveredCourse.name }}</h3>
        <div class="course-details">
          <p><span class="label">学时:</span> {{ hoveredCourse.hours }}小时</p>
          <p><span class="label">学分:</span> {{ hoveredCourse.credits }}分</p>
          <p><span class="label">教师:</span> {{ hoveredCourse.teacher }}</p>
          <p><span class="label">进度:</span> {{ hoveredCourse.progress }}%</p>
        </div>
        <div class="status-indicator" :class="hoveredCourse.status">
          {{ getStatusText(hoveredCourse.status) }}
        </div>
      </div>
      
      <!-- 加载指示器 -->
      <div v-if="isLoading" class="loading-indicator">
        <div class="spinner"></div>
        <p>正在加载3D课程场景...</p>
      </div>
      
      <!-- 帮助提示 -->
      <div class="help-tips">
        <div class="tip">💡 鼠标拖拽可旋转视角</div>
        <div class="tip">💡 滚轮缩放可调整距离</div>
        <div class="tip">💡 点击书本查看课程详情</div>
      </div>
    </div>
  </div>
</template>

<script>
import * as THREE from 'three'
import { gsap } from 'gsap'

export default {
  name: 'Course3D',
  data() {
    return {
      // 3D相关
      scene: null,
      camera: null,
      renderer: null,
      books: [],
      raycaster: new THREE.Raycaster(),
      mouse: new THREE.Vector2(),
      
      // 课程数据
      currentSemester: 0,
      semesters: [
        { name: '2025-1学期', courses: [] },
        { name: '2025-2学期', courses: [] },
        { name: '2024-2学期', courses: [] }
      ],
      courses: [
        {
          id: 1,
          name: '人工智能基础',
          hours: 48,
          credits: 3,
          teacher: '张教授',
          progress: 75,
          status: 'learning',
          semester: 0,
          cover: '/covers/ai-basics.jpg'
        },
        {
          id: 2,
          name: '数据结构与算法',
          hours: 64,
          credits: 4,
          teacher: '李教授',
          progress: 100,
          status: 'completed',
          semester: 0,
          cover: '/covers/data-structure.jpg'
        },
        {
          id: 3,
          name: '机器学习',
          hours: 56,
          credits: 3.5,
          teacher: '王教授',
          progress: 0,
          status: 'not-started',
          semester: 1,
          cover: '/covers/machine-learning.jpg'
        },
        {
          id: 4,
          name: '深度学习',
          hours: 72,
          credits: 4.5,
          teacher: '刘教授',
          progress: 30,
          status: 'learning',
          semester: 1,
          cover: '/covers/deep-learning.jpg'
        },
        {
          id: 5,
          name: '计算机视觉',
          hours: 60,
          credits: 4,
          teacher: '陈教授',
          progress: 100,
          status: 'completed',
          semester: 2,
          cover: '/covers/computer-vision.jpg'
        }
      ],
      
      // UI状态
      hoveredCourse: null,
      cardPosition: { x: 0, y: 0 },
      searchQuery: '',
      isLoading: true,
      filteredCourses: []
    }
  },
  
  mounted() {
    this.initializeCoursesBySemester()
    this.init3D()
    this.animate()
    
    // 添加窗口调整监听
    window.addEventListener('resize', this.onWindowResize)
    
    // 模拟加载完成
    setTimeout(() => {
      this.isLoading = false
    }, 2000)
  },
  
  beforeDestroy() {
    window.removeEventListener('resize', this.onWindowResize)
    if (this.renderer) {
      this.renderer.dispose()
    }
  },
  
  methods: {
    initializeCoursesBySemester() {
      this.courses.forEach(course => {
        this.semesters[course.semester].courses.push(course)
      })
      this.filteredCourses = this.semesters[this.currentSemester].courses
    },
    
    init3D() {
      const container = this.$refs.container3d
      
      // 创建场景
      this.scene = new THREE.Scene()
      this.scene.background = new THREE.Color(0x1a1a2e)
      
      // 创建相机
      this.camera = new THREE.PerspectiveCamera(
        75,
        container.clientWidth / container.clientHeight,
        0.1,
        1000
      )
      this.camera.position.set(0, 5, 15)
      
      // 创建渲染器
      this.renderer = new THREE.WebGLRenderer({ antialias: true })
      this.renderer.setSize(container.clientWidth, container.clientHeight)
      this.renderer.shadowMap.enabled = true
      this.renderer.shadowMap.type = THREE.PCFSoftShadowMap
      container.appendChild(this.renderer.domElement)
      
      // 添加灯光
      this.setupLights()
      
      // 创建书架
      this.createBookshelf()
      
      // 创建书本
      this.createBooks()
      
      // 添加粒子效果
      this.createParticles()
      
      // 添加鼠标事件
      this.setupMouseEvents()
    },
    
    setupLights() {
      // 环境光
      const ambientLight = new THREE.AmbientLight(0x404040, 0.6)
      this.scene.add(ambientLight)
      
      // 主光源
      const directionalLight = new THREE.DirectionalLight(0xffffff, 1)
      directionalLight.position.set(10, 10, 5)
      directionalLight.castShadow = true
      directionalLight.shadow.mapSize.width = 2048
      directionalLight.shadow.mapSize.height = 2048
      this.scene.add(directionalLight)
      
      // 点光源（用于书本高亮）
      const pointLight = new THREE.PointLight(0x00ff88, 0.5, 30)
      pointLight.position.set(0, 8, 8)
      this.scene.add(pointLight)
    },
    
    createBookshelf() {
      // 创建书架结构
      const shelfGeometry = new THREE.BoxGeometry(20, 0.2, 3)
      const shelfMaterial = new THREE.MeshPhongMaterial({ color: 0x8B4513 })
      
      // 创建多层书架
      for (let i = 0; i < 3; i++) {
        const shelf = new THREE.Mesh(shelfGeometry, shelfMaterial)
        shelf.position.y = i * 3 - 2
        shelf.receiveShadow = true
        this.scene.add(shelf)
        
        // 书架支撑柱
        const pillarGeometry = new THREE.BoxGeometry(0.3, 8, 0.3)
        const pillarMaterial = new THREE.MeshPhongMaterial({ color: 0x654321 })
        
        [-9.5, 9.5].forEach(x => {
          const pillar = new THREE.Mesh(pillarGeometry, pillarMaterial)
          pillar.position.set(x, 2, 0)
          pillar.castShadow = true
          this.scene.add(pillar)
        })
      }
    },
    
    createBooks() {
      this.books = []
      const currentCourses = this.semesters[this.currentSemester].courses
      
      currentCourses.forEach((course, index) => {
        const book = this.createSingleBook(course, index)
        this.books.push(book)
        this.scene.add(book)
      })
    },
    
    createSingleBook(course, index) {
      // 书本几何体
      const bookGeometry = new THREE.BoxGeometry(1.5, 2, 0.3)
      
      // 根据课程状态选择材质
      let bookColor = 0x666666 // 默认灰色
      if (course.status === 'completed') {
        bookColor = 0xFFD700 // 金色
      } else if (course.status === 'learning') {
        bookColor = 0x4CAF50 // 绿色
      }
      
      const bookMaterial = new THREE.MeshPhongMaterial({ color: bookColor })
      const book = new THREE.Mesh(bookGeometry, bookMaterial)
      
      // 位置计算
      const row = Math.floor(index / 6)
      const col = index % 6
      book.position.set(
        (col - 2.5) * 3,
        row * 3 - 2,
        1.2
      )
      
      // 添加课程数据
      book.userData = course
      
      // 添加发光效果
      if (course.status === 'completed') {
        this.addGlowEffect(book)
      }
      
      book.castShadow = true
      book.receiveShadow = true
      
      return book
    },
    
    addGlowEffect(book) {
      const glowGeometry = new THREE.BoxGeometry(1.7, 2.2, 0.4)
      const glowMaterial = new THREE.MeshBasicMaterial({
        color: 0xFFD700,
        transparent: true,
        opacity: 0.3
      })
      const glow = new THREE.Mesh(glowGeometry, glowMaterial)
      book.add(glow)
    },
    
    createParticles() {
      const particleCount = 1000
      const particles = new THREE.BufferGeometry()
      const positions = new Float32Array(particleCount * 3)
      
      for (let i = 0; i < particleCount * 3; i += 3) {
        positions[i] = (Math.random() - 0.5) * 50
        positions[i + 1] = (Math.random() - 0.5) * 50
        positions[i + 2] = (Math.random() - 0.5) * 50
      }
      
      particles.setAttribute('position', new THREE.BufferAttribute(positions, 3))
      
      const particleMaterial = new THREE.PointsMaterial({
        color: 0x00ff88,
        size: 0.1
      })
      
      const particleSystem = new THREE.Points(particles, particleMaterial)
      this.scene.add(particleSystem)
    },
    
    setupMouseEvents() {
      const container = this.$refs.container3d
      
      container.addEventListener('mousemove', this.onMouseMove)
      container.addEventListener('click', this.onMouseClick)
      container.addEventListener('wheel', this.onMouseWheel)
      
      let isMouseDown = false
      let previousMousePosition = { x: 0, y: 0 }
      
      container.addEventListener('mousedown', (event) => {
        isMouseDown = true
        previousMousePosition = { x: event.clientX, y: event.clientY }
      })
      
      container.addEventListener('mouseup', () => {
        isMouseDown = false
      })
      
      container.addEventListener('mousemove', (event) => {
        if (isMouseDown) {
          const deltaMove = {
            x: event.clientX - previousMousePosition.x,
            y: event.clientY - previousMousePosition.y
          }
          
          // 旋转相机
          const spherical = new THREE.Spherical()
          spherical.setFromVector3(this.camera.position)
          spherical.theta -= deltaMove.x * 0.01
          spherical.phi += deltaMove.y * 0.01
          spherical.phi = Math.max(0.1, Math.min(Math.PI - 0.1, spherical.phi))
          
          this.camera.position.setFromSpherical(spherical)
          this.camera.lookAt(0, 0, 0)
          
          previousMousePosition = { x: event.clientX, y: event.clientY }
        }
      })
    },
    
    onMouseMove(event) {
      const rect = this.$refs.container3d.getBoundingClientRect()
      this.mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1
      this.mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1
      
      // 射线检测
      this.raycaster.setFromCamera(this.mouse, this.camera)
      const intersects = this.raycaster.intersectObjects(this.books)
      
      if (intersects.length > 0) {
        const intersectedBook = intersects[0].object
        this.hoveredCourse = intersectedBook.userData
        this.cardPosition = {
          x: event.clientX + 10,
          y: event.clientY - 10
        }
        
        // 书本悬浮效果
        gsap.to(intersectedBook.position, {
          duration: 0.3,
          z: 2,
          ease: "power2.out"
        })
        gsap.to(intersectedBook.rotation, {
          duration: 0.3,
          y: 0.1,
          ease: "power2.out"
        })
      } else {
        this.hoveredCourse = null
        
        // 重置所有书本位置
        this.books.forEach(book => {
          gsap.to(book.position, {
            duration: 0.3,
            z: 1.2,
            ease: "power2.out"
          })
          gsap.to(book.rotation, {
            duration: 0.3,
            y: 0,
            ease: "power2.out"
          })
        })
      }
    },
    
    onMouseClick(event) {
      this.raycaster.setFromCamera(this.mouse, this.camera)
      const intersects = this.raycaster.intersectObjects(this.books)
      
      if (intersects.length > 0) {
        const course = intersects[0].object.userData
        this.enterCourse(course)
      }
    },
    
    onMouseWheel(event) {
      const delta = event.deltaY * 0.01
      this.camera.position.multiplyScalar(1 + delta)
      
      // 限制缩放范围
      const distance = this.camera.position.length()
      if (distance < 5) {
        this.camera.position.normalize().multiplyScalar(5)
      } else if (distance > 30) {
        this.camera.position.normalize().multiplyScalar(30)
      }
    },
    
    switchSemester(index) {
      if (index === this.currentSemester) return
      
      this.currentSemester = index
      this.filteredCourses = this.semesters[index].courses
      
      // 清除当前书本
      this.books.forEach(book => {
        this.scene.remove(book)
      })
      this.books = []
      
      // 创建新学期的书本
      this.createBooks()
      
      // 添加切换动画
      this.books.forEach((book, index) => {
        book.position.y -= 10
        gsap.to(book.position, {
          duration: 1,
          y: book.position.y + 10,
          delay: index * 0.1,
          ease: "bounce.out"
        })
      })
    },
    
    startVoiceSearch() {
      // 语音搜索功能
      if ('webkitSpeechRecognition' in window) {
        const recognition = new webkitSpeechRecognition()
        recognition.lang = 'zh-CN'
        recognition.continuous = false
        recognition.interimResults = false
        
        recognition.onresult = (event) => {
          const result = event.results[0][0].transcript
          this.searchQuery = result
          this.filterCourses()
        }
        
        recognition.onerror = (event) => {
          console.error('语音识别错误:', event.error)
        }
        
        recognition.start()
      } else {
        alert('浏览器不支持语音识别功能')
      }
    },
    
    filterCourses() {
      if (!this.searchQuery) {
        this.filteredCourses = this.semesters[this.currentSemester].courses
      } else {
        this.filteredCourses = this.semesters[this.currentSemester].courses.filter(course =>
          course.name.toLowerCase().includes(this.searchQuery.toLowerCase()) ||
          course.teacher.toLowerCase().includes(this.searchQuery.toLowerCase())
        )
      }
      
      // 重新创建书本
      this.books.forEach(book => {
        this.scene.remove(book)
      })
      this.books = []
      this.createBooks()
    },
    
    enterCourse(course) {
      // 书本展开动画
      const selectedBook = this.books.find(book => book.userData.id === course.id)
      if (selectedBook) {
        gsap.to(selectedBook.scale, {
          duration: 0.5,
          x: 3,
          y: 3,
          z: 0.1,
          ease: "power2.out"
        })
        
        gsap.to(selectedBook.position, {
          duration: 0.5,
          z: 5,
          ease: "power2.out"
        })
        
        // 延迟跳转到课程详情
        setTimeout(() => {
          this.$router.push(`/course-3d-classroom/${course.id}`)
        }, 1000)
      }
    },
    
    getStatusText(status) {
      const statusMap = {
        'completed': '已完成',
        'learning': '学习中',
        'not-started': '未开始'
      }
      return statusMap[status] || '未知'
    },
    
    animate() {
      requestAnimationFrame(this.animate)
      
      // 旋转粒子
      if (this.scene.children.length > 0) {
        const particles = this.scene.children.find(child => child.type === 'Points')
        if (particles) {
          particles.rotation.y += 0.001
        }
      }
      
      this.renderer.render(this.scene, this.camera)
    },
    
    onWindowResize() {
      const container = this.$refs.container3d
      this.camera.aspect = container.clientWidth / container.clientHeight
      this.camera.updateProjectionMatrix()
      this.renderer.setSize(container.clientWidth, container.clientHeight)
    }
  }
}
</script>

<style scoped lang="scss">
.course-3d {
  position: relative;
  width: 100%;
  height: 100vh;
  overflow: hidden;
  background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
}

.three-container {
  width: 100%;
  height: 100%;
  position: relative;
}

.ui-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 100;
  
  > * {
    pointer-events: auto;
  }
}

.top-controls {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20px;
  background: rgba(0, 0, 0, 0.3);
  backdrop-filter: blur(10px);
  border-radius: 0 0 20px 20px;
}

.semester-selector {
  display: flex;
  gap: 10px;
  
  .semester-btn {
    padding: 12px 24px;
    background: rgba(255, 255, 255, 0.1);
    color: white;
    border: 2px solid transparent;
    border-radius: 25px;
    cursor: pointer;
    transition: all 0.3s;
    font-weight: 500;
    
    &:hover {
      background: rgba(255, 255, 255, 0.2);
      border-color: #00ff88;
    }
    
    &.active {
      background: linear-gradient(135deg, #00ff88 0%, #00d4aa 100%);
      border-color: #00ff88;
      box-shadow: 0 0 20px rgba(0, 255, 136, 0.5);
    }
  }
}

.search-controls {
  display: flex;
  gap: 15px;
  align-items: center;
  
  .voice-search {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 12px 20px;
    background: rgba(255, 255, 255, 0.1);
    color: white;
    border-radius: 25px;
    cursor: pointer;
    transition: all 0.3s;
    
    &:hover {
      background: rgba(255, 255, 255, 0.2);
      transform: translateY(-2px);
    }
    
    .voice-icon {
      font-size: 18px;
    }
  }
  
  .search-input {
    padding: 12px 20px;
    background: rgba(255, 255, 255, 0.1);
    color: white;
    border: 2px solid transparent;
    border-radius: 25px;
    width: 300px;
    font-size: 14px;
    
    &::placeholder {
      color: rgba(255, 255, 255, 0.7);
    }
    
    &:focus {
      outline: none;
      border-color: #00ff88;
      box-shadow: 0 0 15px rgba(0, 255, 136, 0.3);
    }
  }
}

.course-info-card {
  position: absolute;
  background: rgba(0, 0, 0, 0.9);
  color: white;
  padding: 20px;
  border-radius: 15px;
  backdrop-filter: blur(15px);
  border: 1px solid rgba(255, 255, 255, 0.2);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
  min-width: 250px;
  z-index: 1000;
  
  h3 {
    margin: 0 0 15px 0;
    color: #00ff88;
    font-size: 18px;
  }
  
  .course-details {
    margin-bottom: 15px;
    
    p {
      margin: 5px 0;
      font-size: 14px;
      
      .label {
        color: #00ff88;
        font-weight: 500;
        margin-right: 8px;
      }
    }
  }
  
  .status-indicator {
    padding: 5px 12px;
    border-radius: 12px;
    font-size: 12px;
    text-align: center;
    font-weight: 500;
    
    &.completed {
      background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%);
      color: #333;
    }
    
    &.learning {
      background: linear-gradient(135deg, #4CAF50 0%, #45a049 100%);
      color: white;
    }
    
    &.not-started {
      background: linear-gradient(135deg, #666 0%, #555 100%);
      color: white;
    }
  }
}

.loading-indicator {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  text-align: center;
  color: white;
  
  .spinner {
    width: 50px;
    height: 50px;
    border: 3px solid rgba(255, 255, 255, 0.3);
    border-top: 3px solid #00ff88;
    border-radius: 50%;
    animation: spin 1s linear infinite;
    margin: 0 auto 20px;
  }
  
  p {
    font-size: 16px;
    margin: 0;
  }
}

.help-tips {
  position: absolute;
  bottom: 20px;
  left: 20px;
  
  .tip {
    background: rgba(0, 0, 0, 0.7);
    color: white;
    padding: 8px 15px;
    border-radius: 20px;
    margin-bottom: 10px;
    font-size: 14px;
    backdrop-filter: blur(10px);
  }
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
</style> 